﻿using System.Collections.Generic;
using System.Linq;
using Lucene.Linq.VSTests.DatabaseIntegration.LinqToSql;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lucene.Linq.Search;
using Lucene.Linq.Storage.EntityFramework;
using Lucene.Linq.VSTests.DatabaseIntegration.LinqToSql;

namespace Lucene.Linq.VSTests
{
    [TestClass]
    //[Description(@"Tests the Parallel indexing using the DatabaseIndexSet which requires Northwind database. See app.config for the connection string")]
    public class TestParallelIndexing
    {
        #region Nested type: BatchOrderIndexer

        public class BatchOrderIndexer : ParallelIndexer<Order>
        {
            private readonly IQueryable<Order> _orders;
            private bool _hasMergingFininished;

            public BatchOrderIndexer(IIndex<Order> index, IQueryable<Order> orders)
                : base(index)
            {
                _orders = orders;

                //
                // Break the results IQueryable into pages, then delegate to child indexers
                //

                const int pageSize = 100;
                int pageIndex = 0;

                PagedList<Order> currentPage = orders.ToPagedList(pageIndex, pageSize);
                int pageCount = currentPage.PageCount;

                while (pageIndex < pageCount)
                {
                    AddChild(new OrderIndexer(new Index<Order>(), currentPage.ToList()));
                    pageIndex++;
                    currentPage = orders.ToPagedList(pageIndex, pageSize);
                }
            }

            public override bool Stopped
            {
                get
                {
                    bool pstopped = base.Stopped;
                    if (pstopped)
                    {
                        return _hasMergingFininished;
                    }
                    else
                    {
                        return false;
                    }
                }
            }

            public override void Run()
            {
                // Block while running
                base.Run();

                // Merge docs of child indexers into source
                base.Merge((from c in Children select c.Index.Directory).ToArray());
                _hasMergingFininished = true;
            }
        }

        #endregion

        #region Parallel Indexing

        [TestMethod, Ignore]
        public void Indexing_orders_in_parallel_should_index_all_rows()
        {
            var dbi = new DatabaseIndexSet<NorthwindDataContext>(new NorthwindDataContext());

            using (var indexer = new BatchOrderIndexer(dbi.Get<Order>(), dbi.DataContext.Orders))
            {
                indexer.Run();
            }

            Assert.AreEqual(dbi.Get<Order>().Count, dbi.DataContext.Orders.Count());
            Assert.Inconclusive("For a reason that I cannot explain there seems to be a deadlock");
        }

        #endregion

        #region Nested type: OrderIndexer

        public class OrderIndexer : Indexer<Order>
        {
            private readonly IEnumerable<Order> _orders;

            public OrderIndexer(IIndex<Order> index, IEnumerable<Order> orders)
                : base(index)
            {
                _orders = orders;
            }

            public override void Run()
            {
                Index.Add(_orders);
                Stopped = true;
            }
        }

        #endregion
    }
}